#include <stdio.h>
#include <string.h>

#include <linux/ip.h>
#include <netinet/ip6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/if_ether.h>

#include <pcap.h>

#ifndef NIPQUAD
#define NIPQUAD(addr) \
	                ((unsigned char *)&addr)[0], \
        ((unsigned char *)&addr)[1], \
        ((unsigned char *)&addr)[2], \
        ((unsigned char *)&addr)[3]
#endif

static pcap_t *handle = NULL;

static void pcap_packet_callback( u_char *args, const struct pcap_pkthdr *header, const u_char *packet );

static char * print_mac( char *buff, const unsigned char *addr )
{
	sprintf( buff, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0],addr[1], addr[2], addr[3], addr[4], addr[5] );

	return buff;
}

static void pcap_packet_callback( u_char *args, const struct pcap_pkthdr *header, const u_char *packet )
{
	struct ethhdr *eth = ( struct ethhdr * )packet;
	struct iphdr *iph = ( struct iphdr * )&packet[sizeof( struct ethhdr )];
	char mac[18] = {0};

	printf( "packet len [ %d ].\n", header->len );
	printf( "packet cap len [ %d ].\n", header->caplen );
	
	printf( "Eth source[ %s ], dest[ %s ].\n", print_mac( mac, eth->h_source ), print_mac( mac, eth->h_dest ) );
	printf( "IP:source[ %u.%u.%u.%u ]. dest[ %u.%u.%u.%u ].\n", NIPQUAD( iph->saddr ), NIPQUAD( iph->daddr ) );	


	printf( "-------------------\n\n" );
	return ;
}

int main()
{
	char errbuff[PCAP_ERRBUF_SIZE], *device;
	struct bpf_program filter;

	device = pcap_lookupdev( errbuff );

	if ( device )
		printf( "Success: device [ %s ].\n", device );
	else
		printf( "Error: errbuff [ %s ].\n", errbuff );

	handle = pcap_open_live( device, 44, 0, 0, errbuff );
	if ( !handle ) {
		printf( "PCAP: Open pcap handle failed [ %s ].\n", errbuff );
		return -1;
	}

	/* compile filter */
	pcap_compile( handle, &filter, "icmp", 1, 0 );
	pcap_setfilter( handle, &filter );

	pcap_loop( handle, 0, &pcap_packet_callback, NULL );
	
	pcap_close( handle );

	return 0;
}
